【X68000(Z)アセンブラ講座 第010回 スプライト画像の表示B】 2025/02/12   こんにちは。 今回はスプライトキャラクターを複数同時に動かすプログラムを追加しました。 破線の内側を'SP_SAMP3.s'と言うファイル名で保存して下さい。 ------------------------------------------------------------------------------------------------   ******************************************************************************** * * アプリ名 : SP_SAMP3.x * * スプライト表示のサンプル(3) * * Ver1.00 * ******************************************************************************** * スプライトパレット0から15のうちパレット0はテキストパレットと共用。 include A:\XC\INCLUDE\DOSCALL.MAC * OSコール用マクロの読み込み include A:\XC\INCLUDE\IOCSCALL.MAC * IOCS(BIOS)コール用マクロの読み込み * システム領域のアドレス cg_palette equ $E82000 * CG用パレットデータの先頭アドレス cg_buffer equ $C00000 * CG-VRAMの先頭アドレス cg_scroll_x equ $E80018 * CGスクロール X cg_scroll_y equ $E8001a * CGスクロール Y sp_palette equ $E82200 * スプライト用パレットデータの先頭アドレス sp_pattern equ $EB8000 * スプライトパターンデータの先頭アドレス sp_controll equ $EB0000 * スプライトスクロールレジスターの先頭アドレス vsync equ $E88001 * %00010000でV-Syncチェックする pad1 equ $E9A001 * ゲームパッド1 pad2 equ $E9A003 * ゲームパッド2 * キャラのパラメーターのオフセット値 spx equ 0 * キャラのX座標 spy equ 2 * キャラのY座標 addx equ 4 * キャラのX方向の移動量 addy equ 6 * キャラのY方向の移動量 .cpu 68000 * CPUのタイプ .data * '.data'以降のデータはデータセクションに配置される mx: dc.w 128 * 自キャラX座標 my: dc.w 128 * 自キャラY座標 sp00: dc.b $ff,$ff,$ff,$ff dc.b $ff,$11,$11,$11 dc.b $f1,$11,$11,$11 dc.b $f1,$11,$11,$11 dc.b $f1,$11,$11,$11 dc.b $f1,$11,$11,$11 dc.b $f1,$11,$11,$11 dc.b $f1,$11,$11,$11 dc.b $f1,$11,$11,$11 dc.b $f1,$11,$11,$11 dc.b $f1,$11,$11,$11 dc.b $f1,$11,$11,$11 dc.b $f1,$11,$11,$11 dc.b $f1,$11,$11,$11 dc.b $f1,$11,$11,$11 dc.b $ff,$ff,$ff,$ff dc.b $ff,$ff,$ff,$ff dc.b $11,$11,$11,$1f dc.b $11,$11,$11,$1f dc.b $11,$11,$11,$1f dc.b $11,$11,$11,$1f dc.b $11,$11,$11,$1f dc.b $11,$11,$11,$1f dc.b $11,$11,$11,$1f dc.b $11,$11,$11,$1f dc.b $11,$11,$11,$1f dc.b $11,$11,$11,$1f dc.b $11,$11,$11,$1f dc.b $11,$11,$11,$1f dc.b $11,$11,$11,$1f dc.b $11,$11,$11,$1f dc.b $ff,$ff,$ff,$ff sppal01: * GGGGG RRRRR BBBBB A dc.w %00000_00000_00000_0 dc.w %00000_00000_11111_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %11111_11111_11111_0 .bss * '.bss'以降データバッファ spbuf: dc.w 32 * キャラ管理バッファ (spx,spy,addx,addy)x8 .text * '.text'以降のプログラムはテキストセクションに配置される start: * スタートアドレス * マウスカーソルをオフにする moveq.l #_OS_CUROF,d0 trap #15 * ランダム関数の初期化 move.l #23456,d0 * d0.lにランダムのシードを代入する dc.w $FE0D * ランダムのシードを設定する * ユーザーモードからスーパーバイザーモードに移行する moveq.l #_B_SUPER,d0 * d0にIOCS(BIOS)機能番号を代入 move.l #0,d1 * 数値0をd1に代入 movea.l d1,a1 * d1をa1にコピー trap #15 * IOCSコール実行 * 画面モードの設定 moveq.l #_CRTMOD,d0 * 画面モードの設定 move.w #10,d1 * 画面モードの番号 : 16 = 768x512x4bit / 10 = 256x256x8bit trap #15 * 画面をクリアして表示をオンにする moveq.l #_G_CLR_ON,d0 * 画面をクリアして表示をオンにする trap #15 * スプライト表示をオンにする moveq.l #_SP_ON,d0 trap #15 bsr set_palette * スプライトパレット設定ルーチンの呼び出し bsr set_sprite * スプライトパターンデータの定義ルーチンの呼び出し bsr init_chara * キャラの初期化の呼び出し loop: * メインループ開始 * V-Syncビットを監視してメインループを60fpsで動作させるタイミングを取る movea.l #vsync,a0 vsync_1: move.b (a0),d0 and.b #$10,d0 tst.b d0 beq vsync_1 vsync_2: move.b (a0),d0 and.b #$10,d0 tst.b d0 bne vsync_2 bsr move_mychara * ゲームパッドでスプライトの座標を移動するルーチンを呼ぶ bsr move_chara * キャラの移動 * スプライトの表示 moveq.l #0,d0 * 表示するスプライト番号(0 - 127) move.w mx,d1 * スプライトX座標(0 - 1023) move.w my,d2 * スプライトY座標(0 - 1023) move.w #$0101,d3 * スプライト情報 move.w #3,d4 * プライオリティ bsr put_sprite * スプライト表示ルーチンの呼び出す * [ESC]キーが押されたら終了処理'end:'にジャンプする moveq.l #_BITSNS,d0 moveq.l #0,d1 trap #15 and.b #%00000010,d0 tst.b d0 bne end bra loop * メインループの最初にジャンプする end: moveq.l #_CRTMOD,d0 move.w #16,d1 trap #15 * マウスカーソルをオンにする moveq.l #_OS_CURON,d0 trap #15 * スーパーバイザーモードからユーザーモードに戻る moveq.l #_B_SUPER,d0 move.l SP,a1 trap #15 * アプリ終了 dc.w _EXIT * OSコール実行 : _EXIT = プログラムの終了 * RGBQUAD { Blue8, Green8, Red8, Reserved8 } = %RRRRRRRR_GGGGGGGG_BBBBBBBB_AAAAAAAA * palette { Green5, Red5, Blue5, Alpha1 } = %GGGGG_RRRRR_BBBBB_A * Set Sprite Palette set_palette: movea.l #sp_palette,a0 * スプライト用パレットレジスターアドレス adda.l #32,a0 lea sppal01,a1 * パレットデータバッファアドレス moveq.l #0,d7 set_palette_1: move.w (a1)+,(a0)+ addq.w #1,d7 * 色番号を次の番号に更新する cmp.w #16,d7 * 現在の色番号と16を比較する blt set_palette_1 * 現在の色番号が16未満ならアドレスset_palette_1に飛ぶ rts * 呼出元に戻る * スプライトパターンの定義 set_sprite: lea sp00,a0 movea.l #sp_pattern,a1 adda.l #128,a1 moveq.l #0,d7 set_sprite_1: move.l (a0)+,(a1)+ addq.w #1,d7 cmp.w #32,d7 blt set_sprite_1 rts put_sprite: * d0.w = 表示するスプライトの番号(0 - 127) * d1.w = %000000XXXXXXXXXX * X座標 * d2.w = %000000YYYYYYYYYY * Y座標 * d3.w = %VH00CCCCSSSSSSSS * スプライト情報 * d4.w = %00000000000000PP * プライオリティ設定 movem.l d0/a0,-(sp) movea.l #sp_controll,a0 ext.l d0 lsl.w #3,d0 * d0の値を8倍にする adda.l d0,a0 move.w d1,(a0)+ move.w d2,(a0)+ move.w d3,(a0)+ move.w d4,(a0)+ movem.l (sp)+,d0/a0 rts move_mychara: movea.l #pad1,a0 * ゲームパッドのボタンの押下状態を取得し座標を更新する move.b (a0),d0 * 左キーを押したらmxから1を引く move.b d0,d1 and.b #%0000_0100,d1 tst.b d1 bne move_mychara_1 sub.w #1,mx move_mychara_1: * 右キーを押したらmxに1を足す move.b d0,d1 and.b #%0000_1000,d1 tst.b d1 bne move_mychara_2 add.w #1,mx move_mychara_2: * 上キーを押したらmyから1を引く move.b d0,d1 and.b #%0000_0001,d1 tst.b d1 bne move_mychara_3 sub.w #1,my move_mychara_3: * 下キーを押したらmyに1を足す move.b d0,d1 and.b #%0000_0010,d1 tst.b d1 bne move_mychara_4 add.w #1,my move_mychara_4: rts * 複数キャラの初期化 init_chara: lea spbuf,a0 moveq.l #0,d7 init_chara_1: * X座標の初期値を決める dc.w $FE0E * d0.lに0から32767のランダム値を返す mulu #240,d0 * 直後の命令と組み合わせで divu #32767,d0 * ランダム値を0から240の範囲に変換する move.w d0,spx(a0) * ランダム値をアドレス(a0+spx)に格納 * Y座標の初期値を決める dc.w $FE0E mulu #240,d0 divu #32767,d0 move.w d0,spy(a0) * X座標の移動ピクセル数を決める dc.w $FE0E mulu #5,d0 divu #32767,d0 addq.w #1,d0 move.w d0,addx(a0) * Y座標の移動ピクセル数を決める dc.w $FE0E mulu #5,d0 divu #32767,d0 addq.w #1,d0 move.w #1,addy(a0) addq.l #8,a0 * 次のキャラ管理バッファアドレスに変更 addq.w #1,d7 cmp.w #8,d7 blt init_chara_1 rts * 複数のキャラの移動 move_chara: lea spbuf,a0 moveq.l #1,d0 move_chara_1: * X座標の移動 move.w spx(a0),d1 add.w addx(a0),d1 cmp.w #272,d1 blt move_chara_2 sub.w #272,d1 move_chara_2: move.w d1,spx(a0) * Y座標の移動 move.w spy(a0),d2 add.w addy(a0),d2 cmp.w #272,d2 blt move_chara_3 sub.w #272,d2 move_chara_3: move.w d2,spy(a0) move.w #$0101,d3 moveq.l #3,d4 bsr put_sprite addq.l #8,a0 * 次のキャラ管理バッファアドレスに変更 addq.w #1,d0 cmp.w #9,d0 blt move_chara_1 rts ------------------------------------------------------------------------------------------------ コマンドプロンプトから、 A>as SP_SAMP3.s [Enter] A>lk SP_SAMP3.o [Enter] A>SP_SAMP3.x [Enter] のように入力すると複数のスプライトが動作します。 終了は[ESC]キーです。 説明し忘れていましたが、 スプライトの座標の原点は画面のX座標から16ピクセル左でY座標は16ピクセル上です。 スプライトを座標(0,0)で表示しようとしても左に16ピクセル上にピクセルずれて表示されるので XY座標それぞれに16を足すと正常に表示されます。 16ピクセル未満の座標を指定するとはみ出し処理されて表示されます。 [EOF]